Math.clamp = function(val, min, max)
{
  if (val < min)
    return min;
  if (val > max)
    return max;
  return val;
};

Math.mapToInt = function(val, min, max, mapMin, mapMax)
{
  return Math.round(Math.map(val, min, max, mapMin, mapMax));
};

Math.map = function(val, min, max, mapMin, mapMax)
{
  val = (val - min) / (max - min);
  val = Math.clamp(val, 0, 1);
  var result = (mapMin + val * (mapMax - mapMin));
  if (!isFinite(result)) result = mapMax;
  return result;
};

function Color(r, g, b)
{
  this.r = Math.floor(Math.clamp(r, 0, 255));
  this.g = Math.floor(Math.clamp(g, 0, 255));
  this.b = Math.floor(Math.clamp(b, 0, 255));
}

Color.parseHex = function(hex)
{
  hex = hex.toLowerCase();
  hex = hex.replace("#", "").replace("0x", "");

  var r = hToD(hex.substr(0, 2));
  var g = hToD(hex.substr(2, 2));
  var b = hToD(hex.substr(4, 2));

  return new Color(r, g, b);
};

Color.prototype.toHex = function()
{
  return dToH(this.r) + dToH(this.g) + dToH(this.b);
};

Color.lerp = function(val, min, max, minColor, maxColor)
{
  var r = Math.map(val, min, max, minColor.r, maxColor.r);
  var g = Math.map(val, min, max, minColor.g, maxColor.g);
  var b = Math.map(val, min, max, minColor.b, maxColor.b);

  return new Color(r, g, b);
};

function dToH(d, padding)
{
  var hex = Number(d).toString(16);
  padding = (typeof (padding) === "undefined" || padding === null) ? padding = 2
      : padding;

  while (hex.length < padding)
  {
    hex = "0" + hex;
  }

  return hex;
}

function hToD(h)
{
  return parseInt(h, 16);
}
